#include "formulaevaluator.h"
#include "spreadsheetmodel.h"  // 包含了完整定义

//定义正则表达式来匹配
const QRegularExpression FormulaEvaluator::cellRefRegex(R"(^([A-Za-z]+)(\d+)$)");//单元格引用 如A1
const QRegularExpression FormulaEvaluator::functionRegex(R"(^([A-Za-z]+)\((.*)\)$)");//函数调用 如SUM(A1:A10) → 函数名 SUM，参数 A1:A10
const QRegularExpression FormulaEvaluator::rangeRegex(R"(^([A-Za-z]+\d+):([A-Za-z]+\d+)$)");//单元格范围 A1:B2 → 范围从 A1 到 B2
const QRegularExpression FormulaEvaluator::arithmeticRegex(R"((.+?)([+\-*/])(.+))");//匹配运算符

//构造函数 初始化 注册内置函数
FormulaEvaluator::FormulaEvaluator(SpreadsheetModel* model, QObject* parent)
    : QObject(parent), m_model(model)
{
    // 注册内置函数
    // SUM 函数
    registerFunction("SUM", [](const QVector<QVariant>& args) {
        double sum = 0;
        for (const auto& arg : args) {
            bool ok;
            double val = arg.toDouble(&ok);
            if (ok) sum += val;
        }
        return sum;
    });

    // AVERAGE 函数
    registerFunction("AVERAGE", [](const QVector<QVariant>& args) {
        if (args.isEmpty()) return 0.0;
        double sum = 0;
        for (const auto& arg : args) {
            bool ok;
            double val = arg.toDouble(&ok);
            if (ok) sum += val;
        }
        return sum / args.size();
    });

    // MAX 函数
    registerFunction("MAX", [](const QVector<QVariant>& args) {
        if (args.isEmpty()) return 0.0;
        double max = -std::numeric_limits<double>::infinity(); // 初始为负无穷
        for (const auto& arg : args) {
            bool ok;
            double val = arg.toDouble(&ok);
            if (ok && val > max) max = val;// 更新最大值
        }
        return max;
    });

    // MIN 函数
    registerFunction("MIN", [](const QVector<QVariant>& args) {
        if (args.isEmpty()) return 0.0;
        double min = std::numeric_limits<double>::infinity();// 初始为正无穷
        for (const auto& arg : args) {
            bool ok;
            double val = arg.toDouble(&ok);
            if (ok && val < min) min = val;// 更新最小值
        }
        return min;
    });

    // 注册运算符函数
    registerFunction("+", [](const QVector<QVariant>& args) -> QVariant{
        if (args.size() != 2) return QVariant("#INVALID_ARGS");
        return args[0].toDouble() + args[1].toDouble();
    });

    registerFunction("-", [](const QVector<QVariant>& args) -> QVariant{
        if (args.size() != 2) return QVariant("#INVALID_ARGS");
        return args[0].toDouble() - args[1].toDouble();
    });

    registerFunction("*", [](const QVector<QVariant>& args) -> QVariant{
        if (args.size() != 2) return QVariant("#INVALID_ARGS");
        return args[0].toDouble() * args[1].toDouble();
    });

    registerFunction("/", [](const QVector<QVariant>& args) -> QVariant{
        if (args.size() != 2) return QVariant("#INVALID_ARGS");
        double divisor = args[1].toDouble();
        if (divisor == 0) return QVariant("#DIV/0!");
        return args[0].toDouble() / divisor;
    });
}

//判断是否为公式（字符串是否以 = 开头）
bool FormulaEvaluator::isFormula(const QString& text) const
{
    return text.startsWith('=');
}

//将行列索引转换为单元格引用
QString FormulaEvaluator::getCellReference(int row, int col) const
{
    QString colName;
    while (col >= 0) {
        colName.prepend(QChar('A' + (col % 26)));// 将数字转换为字母（A-Z）
        col = col / 26 - 1;// 将数字转换为字母（A-Z）
    }
    return colName + QString::number(row + 1);// 组合列名和行号（如 "A1"）
}

// 将单元格引用解析为行号和列号
void FormulaEvaluator::parseCellReference(const QString& ref, int& row, int& col) const
{
    QRegularExpressionMatch match = cellRefRegex.match(ref);// 用正则匹配单元格引用
    if (match.hasMatch()) {
        QString colStr = match.captured(1);// 提取列名字母部分
        col = 0;
        for (int i = 0; i < colStr.length(); ++i) {
            col = col * 26 + colStr[i].toUpper().unicode() - 'A';// 字母转数字
        }
        row = match.captured(2).toInt() - 1;//行号转 0-based
    }
}

//注册函数 参数为函数名和函数实现
void FormulaEvaluator::registerFunction(const QString& name, std::function<QVariant(const QVector<QVariant>&)> func)
{
    //std::function<QVariant(const QVector<QVariant>&)>
    //一个通用的函数包装器，可以接受 Lambda、普通函数或函数对象。
    //参数：const QVector<QVariant>&
    m_functions[name.toUpper()] = func;//用于存储函数名与实现的映射。
}

// 计算给定公式的值
QVariant FormulaEvaluator::evaluate(const QString& formula, int row, int col)const
{
    // row 和 col：当前单元格的行列索引（用于解析相对引用，如 A1）。
    if (!isFormula(formula)) {//调用辅助方法 检查字符串是否以 = 开头。
        return formula;
    }
    //跳过首字符 =，提取公式主体（如 "=A1+B2" → "A1+B2"）。
    QString expr = formula.mid(1).trimmed();
    return evaluateExpression(expr, row, col);
}

//解析并计算表达式
QVariant FormulaEvaluator::evaluateExpression(const QString& expr, int currentRow, int currentCol)const
{
    // const QString& expr 待计算的表达式（如 "A1+B2"、"SUM(A1:A10)" 或 "42"）

    // 检查是否为算术表达式（可以处理多运算符）
    if (expr.contains(QRegularExpression(arithmeticRegex))) {
        return evaluateArithmeticExpression(expr, currentRow, currentCol);
    }

    // 检查是否为函数调用
    QRegularExpressionMatch funcMatch = functionRegex.match(expr);
    if (funcMatch.hasMatch()) {
        // 处理函数逻辑（如求和、平均值等)
        return evaluateFunction(funcMatch.captured(1), funcMatch.captured(2), currentRow, currentCol);
    }

    // 检查是否为范围引用
    QRegularExpressionMatch rangeMatch = rangeRegex.match(expr);
    if (rangeMatch.hasMatch()) {
        // 调用 evaluateRange 计算范围内所有单元格的值（如求和、最大值等）
        QVector<QVariant> values = evaluateRange(expr, currentRow, currentCol).value<QVector<QVariant>>();
        // 如果范围内只有一个值，直接返回该值
        if (values.size() == 1) {
            return convertToNumberIfPossible(values[0]);
        }
        return QVariant::fromValue(values);
    }

    // 检查是否为单元格引用
    QRegularExpressionMatch cellMatch = cellRefRegex.match(expr);
    if (cellMatch.hasMatch()) {
        int row, col;
        // 将单元格引用（如 "B3"）转换为行列索引（row=2, col=1）
        parseCellReference(expr, row, col);
        if (row >= 0 && row < m_model->rowCount() &&
            col >= 0 && col < m_model->columnCount()) {
            QVariant data = m_model->QStandardItemModel::data(m_model->index(row, col));
            if (data.isValid()) {
                bool ok;
                double num = data.toDouble(&ok);  // 尝试转换为数字
                return ok ? num : data;  // 返回数字或原始值
            }
        }
        return 0;
    }

    //处理字面量（数字或字符串）
    bool ok;
    double num = expr.toDouble(&ok);
    if(ok){
        return num;
    }
    else return expr;
}

// 解析并执行函数调用，处理参数并返回计算结果
QVariant FormulaEvaluator::evaluateFunction(const QString& funcName, const QString& args, int currentRow, int currentCol)const
{
    // 解析并执行函数调用，处理参数并返回计算结果。
    // 检查函数是否存在
    if (!m_functions.contains(funcName.toUpper())) {
        return QString("#UNKNOWN_FUNCTION");
    }

    //定义辅助变量
    QStringList argList;//参数表
    QString currentArg;//遍历字符串
    int parenLevel = 0;//记录层数

    // 遍历参数字符串 拆分
    for (const QChar& c : args) {
        if (c == '(') {
            parenLevel++;
            currentArg += c;
        } else if (c == ')') {
            parenLevel--;
            currentArg += c;

        } else if (c == ',' && parenLevel == 0) {
            // 遇到逗号 , 且在最外层
            // 将当前参数加入列表
            argList << currentArg.trimmed();
            currentArg.clear();
        } else {
            currentArg += c;
        }
    }

    //如果不为空
    if (!currentArg.isEmpty()) {
        //加入参数表
        argList << currentArg.trimmed();
    }

    //定义函数参数
    QVector<QVariant> evaluatedArgs;

    // 递归计算参数值
    for (const QString& arg : argList) {
        //保存结果
        QVariant result = evaluateExpression(arg, currentRow, currentCol);
        // 如果结果是范围(QVariantList)，展开它
        if (result.canConvert<QVector<QVariant>>()) {
            QVector<QVariant> rangeValues = result.value<QVector<QVariant>>();
            for (const QVariant& val : rangeValues) {
                evaluatedArgs << convertToNumberIfPossible(val);
            }
        } else {
            evaluatedArgs << convertToNumberIfPossible(result);
        }
    }
    //返回函数结果
    return m_functions[funcName.toUpper()](evaluatedArgs);
}

// 解析单元格范围，获取范围内的值并返回
QVariant FormulaEvaluator::evaluateRange(const QString& range, int currentRow, int currentCol)const
{
    QRegularExpressionMatch match = rangeRegex.match(range);
    if (!match.hasMatch()) {
        // 若输入不匹配（如 "A1B2" 或 "A1:"），返回错误 #INVALID_RANGE。
        return QString("#INVALID_RANGE");
    }

    // 提取范围的起始和结束位置
    QString from = match.captured(1);
    QString to = match.captured(2);
    // 获取范围内的值
    QVector<QVariant> values = getRangeValues(from, to, currentRow, currentCol);

    // 处理空范围
    if(values.isEmpty()){
        return 0;
    }
    return QVariant::fromValue(values);;
}

// 解析单元格范围，从数据模型中获取范围内的有效值
QVector<QVariant> FormulaEvaluator::getRangeValues(const QString& from, const QString& to, int currentRow, int currentCol)const
{
    int fromRow, fromCol, toRow, toCol;
    parseCellReference(from, fromRow, fromCol);// 解析起始单元格行列
    parseCellReference(to, toRow, toCol); // 解析结束单元格行列

    // 调整相对引用
    // 如果行列索引为负值（表示相对引用），则替换为当前行列（currentRow/currentCol）。
    if (fromCol < 0) fromCol = currentCol;// 修正起始列
    if (fromRow < 0) fromRow = currentRow;// 修正起始列
    if (toCol < 0) toCol = currentCol;// 修正结束列
    if (toRow < 0) toRow = currentRow; // 修正结束行

    // 遍历范围内的单元格
    QVector<QVariant> values;
    // 使用 qMin 和 qMax 确保正确处理反向范围
    for (int row = qMin(fromRow, toRow); row <= qMax(fromRow, toRow); ++row) {
        for (int col = qMin(fromCol, toCol); col <= qMax(fromCol, toCol); ++col) {
            if (row >= 0 && row < m_model->rowCount() &&
                col >= 0 && col < m_model->columnCount()) {
                //获取单元格数据
                QVariant data = m_model->QStandardItemModel::data(m_model->index(row, col),Qt::EditRole);
                if (data.isValid()) {
                    values << data;
                }
            }
        }
    }
    return values;
}

//处理带运算符的表达式
QVariant FormulaEvaluator::evaluateArithmeticExpression(const QString &expr, int currentRow, int currentCol)const
{
    // 尝试匹配第一个运算符
    QRegularExpressionMatch match = arithmeticRegex.match(expr);
    if (!match.hasMatch()) {
        // 如果没有运算符，直接计算表达式
        return evaluateExpression(expr.trimmed(), currentRow, currentCol);
    }
    QString left = match.captured(1).trimmed();
    QString op = match.captured(2).trimmed();
    QString right = match.captured(3).trimmed();

    // 递归计算左右操作数
    QVariant leftVal = evaluateArithmeticExpression(left, currentRow, currentCol);
    QVariant rightVal = evaluateArithmeticExpression(right, currentRow, currentCol);

    // 转换为数字
    bool ok1, ok2;
    double num1 = leftVal.toDouble(&ok1);
    double num2 = rightVal.toDouble(&ok2);
    if (!ok1 || !ok2) {
        return QString("#VALUE!");
    }
    // 调用对应的运算符函数
    return m_functions[op](QVector<QVariant>{num1, num2});
}

// 尝试将值转换为数字
QVariant FormulaEvaluator::convertToNumberIfPossible(const QVariant& value)const
{
    if (value.isNull() || !value.isValid()) {
        return 0;
    }

    bool ok;
    double num = value.toDouble(&ok);
    return ok ? num : value;
}
